OpenCV: Image Histogram Calculations 您所在的位置:网站首页 OpenCV Histograms OpenCV: Image Histogram Calculations

OpenCV: Image Histogram Calculations

2024-07-15 19:19| 来源: 网络整理| 查看: 265

OpenCV: Image Histogram CalculationsSasani Perera

Sasani Perera

·

Follow

7 min read·Jul 14, 2023

--

Image histograms provide valuable insights into the distribution of pixel intensities in an image. By understanding the histogram, you can gain information about the image’s contrast, brightness, and overall tonal distribution. This knowledge can be useful for tasks like image enhancement, image segmentation, and feature extraction.

This article aims to provide a clear and comprehensive guide to learning how to perform image histogram calculations using OpenCV. By understanding and applying histogram analysis techniques, you are enabled to enhance image quality, perform thresholding operations, analyze colour compositions, extract useful features, and visualize and understand images more effectively.

Image Histogram

Every image is composed of individual pixels, which are like tiny dots on a grid. Let’s say we have an image with a size of 250 columns and 100 rows, totalling 2500 pixels. Each of these pixels can have a different colour value, represented by a number ranging from 0 to 255 (for a greyscale image as we discussed in the earlier article).

To visualize the distribution of colour values within the image, we can create a histogram. This histogram acts as a set of bar graphs that displays the number of pixels having the same colour value. By comparing the heights of the bars, we can easily identify which colour values are more prominent or occur more frequently in the image. This graphical representation provides valuable insights into the overall colour composition and distribution of an image.

Image Histogram (Single colour)

Now remember, pixel intensity 0 → Black255 → White

So the image must contain more Black pixels if our histogram is shifted to the left (left-skewed) and the image must contain more White pixels if our histogram is shifted to the right (right-skewed).

Left-skewed and Right-skewed histograms

So I am sure that you thoroughly understand that,More black → darker imageMore white → brighter image

Now let us do the Histogram Calculation in OpenCV.

First, we’ll load the image and visualize it.

#import necessary librariesimport cv2import numpy as npimport matplotlib.pyplot as plt

#using opencv to read an image#BGR Imageimage = cv2.imread("C:/users/public/pictures/nature.jpg")

#visualizingcv2.namedWindow("BGR Image", cv2.WINDOW_NORMAL);cv2.imshow("BGR Image",image);

cv2.waitKey(0) & 0xFF cv2.destroyAllWindows()

Before we plot the histogram, we can separate the colour channels in this image.

B = image[:,:,0] #blue layerG = image[:,:,1] #green layerR = image[:,:,2] #red layer

Now we calculate and find the histograms for each layer using OpenCV function cv.calcHist() and plot those histograms, using OpenCV and Matplotlib functions

cv.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]])

● images: it is the source image of type uint8 or float32. it should be given in square brackets, ie, “[img]”.

● channels: it is also given in square brackets. It is the index of the channel for which we calculate the histogram. For example, if the input is a grayscale image, its value is [0]. For colour images, you can pass [0], [1] or [2] to calculate histograms of blue, green or red channels respectively.

● mask: mask image. To find the histogram of the full image, it is given as “None”. But if you want to find a histogram of a particular region of the image, you have to create a mask image for that and give it as a mask.

● histSize: this represents our BIN count. Need to be given in square brackets. For full scale, we pass [256].

● ranges: this is our RANGE. Normally, it is [0,256].

B_histo = cv2.calcHist([image],[0], None, [256], [0,256])G_histo = cv2.calcHist([image],[1], None, [256], [0,256])R_histo = cv2.calcHist([image],[2], None, [256], [0,256])

Now we plot these in subplots using matplotlib.

You may try this on images of different settings.

COMPLETE CODE

#import necessary librariesimport cv2import numpy as npimport matplotlib.pyplot as plt

#using opencv to read an image#BGR Imageimage = cv2.imread("C:/users/public/pictures/nature.jpg")

#seperating colour channelsB = image[:,:,0] #blue layerG = image[:,:,1] #green layerR = image[:,:,2] #red layer

#calculating histograms for each channelB_histo = cv2.calcHist([image],[0], None, [256], [0,256])G_histo = cv2.calcHist([image],[1], None, [256], [0,256])R_histo = cv2.calcHist([image],[2], None, [256], [0,256])

#visualizing histogramsplt.subplot(2, 2, 1)plt.plot(B_histo, 'b')plt.subplot(2, 2, 2)plt.plot(G_histo, 'g')plt.subplot(2, 2, 3)plt.plot(R_histo, 'r')

#visualizing imagecv2.namedWindow("BGR Image", cv2.WINDOW_NORMAL);cv2.imshow("BGR Image",image);cv2.waitKey(0) & 0xFF cv2.destroyAllWindows()

Overexposed and Underexposed Images

Then we can extend this idea to identify overexposed (too bright) images and underexposed (too dark) images.

Let us see the histograms of these images.

Histogram plotting using Matplotib and OpenCV

Clearly, one histogram is left-skewed which the image is underexposed and another histogram is right-skewed which the image is overexposed.

Here, we can clearly understand if an image is underexposed or overexposed just by looking at its histograms.

Histogram Equalization

Consider an underexposed or overexposed image whose pixel values are confined to some specific range of values only. For eg: the brighter image will have all pixels confined to high values.

But a good image will have pixels from all regions of the image. So you need to stretch this histogram to either end. This normally improves the contrast of the image.

When performing histogram equalization on colour images we usually apply the process separately to the Red, Green, and Blue components of the RGB colour values in the image.

First, we read the image and split the image into three colour layers.

import cv2import numpy as npimport matplotlib.pyplot as plt

#using opencv to read an image#BGR Imageimage = cv2.imread("C:/users/public/pictures/underexposed_image.jpg")

#seperating colour channelsB = image[:,:,0] #blue layerG = image[:,:,1] #green layerR = image[:,:,2] #red layer

Then we use cv.equalizeHist() to equalize each of the colour layers’ histograms. Visualize them using Matplotlib and OpenCV.

b_equi = cv2.equalizeHist(B)g_equi = cv2.equalizeHist(G)r_equi = cv2.equalizeHist(R)

plt.imshow(b_equi)plt.title("b_equi")plt.show()plt.imshow(g_equi)plt.title("g_equi")plt.show()plt.imshow(r_equi)plt.title("r_equi")plt.show()

R, G, and B layers equalized using OpenCV

With the equalized colour layers’ we calculate each colour’s histogram using cv.calcHist(). And then plot them all.

B_histo = cv2.calcHist([b_equi],[0], None, [256], [0,256]) G_histo = cv2.calcHist([g_equi],[0], None, [256], [0,256])R_histo = cv2.calcHist([r_equi],[0], None, [256], [0,256])

plt.subplot(2, 2, 1)plt.plot(G_histo, 'g')plt.subplot(2, 2, 2)plt.plot(R_histo, 'r')plt.subplot(2, 2, 3)plt.plot(B_histo, 'b')

You must have noticed that we have used only [0]s in the ‘channels’ place. In the previous case, we used all [0], [1] and [2]. This is due to, the availability of split channels. Therefore there’s only 1 channel. Hence for all histograms, ‘channels’ is [0]

Optionally, you can get the histograms of each channel in the original image and plot them with the equalized colour layers.

#calculate histograms for each channel seperately#Equilized channelsB_histo = cv2.calcHist([b_equi],[0], None, [256], [0,256]) G_histo = cv2.calcHist([g_equi],[0], None, [256], [0,256])R_histo = cv2.calcHist([r_equi],[0], None, [256], [0,256])#Original channelsBO_histo = cv2.calcHist([image],[0], None, [256], [0,256]) GO_histo = cv2.calcHist([image],[1], None, [256], [0,256])RO_histo = cv2.calcHist([image],[2], None, [256], [0,256])

#visualize the channel histograms seperatelyplt.figure(figsize=(10,12), )

plt.subplot(3, 2, 1)plt.title("Green Original")plt.plot(GO_histo, 'g')

plt.subplot(3, 2, 2)plt.title("Green Equilized")plt.plot(G_histo, 'g')

plt.subplot(3, 2, 3)plt.title("Red Original")plt.plot(RO_histo, 'r')

plt.subplot(3, 2, 4)plt.title("Red Equilized")plt.plot(R_histo, 'r')

plt.subplot(3, 2, 5)plt.title("Blue Original")plt.plot(BO_histo, 'b')

plt.subplot(3, 2, 6)plt.title("Blue Equilized")plt.plot(B_histo, 'b')

Original image colours’ histograms vs equalized image colours’ histogram

Moving on to the next step, what we have now are only layers. To get an image out of these, we need to merge these.

equi_im = cv2.merge([b_equi,g_equi,r_equi])

Now let us see the equalized image and the original image side by side.

cv2.namedWindow("Original Image", cv2.WINDOW_NORMAL);cv2.imshow("Original Image",image);cv2.namedWindow("New Image", cv2.WINDOW_NORMAL);cv2.imshow("New Image",equi_im);

cv2.waitKey(0) & 0xFF cv2.destroyAllWindows()

Image equalized using OpenCV

COMPLETE CODE

import cv2import numpy as npimport matplotlib.pyplot as plt

#using opencv to read an image#BGR Imageimage = cv2.imread("C:/users/public/pictures/underexposed_image.jpg")

#seperating colour channelsB = image[:,:,0] #blue layerG = image[:,:,1] #green layerR = image[:,:,2] #red layer

#equilize each channel seperatelyb_equi = cv2.equalizeHist(B)g_equi = cv2.equalizeHist(G)r_equi = cv2.equalizeHist(R)

#calculate histograms for each channel seperatelyB_histo = cv2.calcHist([b_equi],[0], None, [256], [0,256]) G_histo = cv2.calcHist([g_equi],[0], None, [256], [0,256])R_histo = cv2.calcHist([r_equi],[0], None, [256], [0,256])

#merge thechannels and create new imageequi_im = cv2.merge([b_equi,g_equi,r_equi])

#visualize the equilized channels seperatelyplt.imshow(b_equi)plt.title("b_equi")plt.show()plt.imshow(g_equi)plt.title("g_equi")plt.show()plt.imshow(r_equi)plt.title("r_equi")plt.show()

#visualize the channel histograms seperatelyplt.subplot(2, 2, 1)plt.plot(G_histo, 'g')plt.subplot(2, 2, 2)plt.plot(R_histo, 'r')plt.subplot(2, 2, 3)plt.plot(B_histo, 'b')

#visualize the original and equilized imagescv2.namedWindow("Original Image", cv2.WINDOW_NORMAL);cv2.imshow("Original Image",image);cv2.namedWindow("New Image", cv2.WINDOW_NORMAL);cv2.imshow("New Image",equi_im);

cv2.waitKey(0) & 0xFF cv2.destroyAllWindows()

Thanks For Reading, Follow For More.Happy learning!



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有